package com.snow.useviewdemo.util.lifecyler;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created by zhaoyingtao
 * Date: 2020/12/15
 * Describe:
 */
public class SNForegroundCallbacks implements Application.ActivityLifecycleCallbacks {
    public static final long CHECK_DELAY = 500;
    public static final String TAG = SNForegroundCallbacks.class.getName();

    private static SNForegroundCallbacks INSTANCE;
    private boolean foreground = false;
    private boolean paused = true;
    private Handler handler = new Handler();
    private List<SNLifecycleListener> listeners = new CopyOnWriteArrayList<SNLifecycleListener>();
    private Runnable check;
    private static List<Class> whiteClass = new ArrayList<>();

    public static SNForegroundCallbacks init(Application application) {
        if (INSTANCE == null) {
            INSTANCE = new SNForegroundCallbacks();
            application.registerActivityLifecycleCallbacks(INSTANCE);
        }
        return INSTANCE;
    }

    public static void setWhiteClass(List<Class> classList) {
        whiteClass.clear();
        whiteClass.addAll(classList);
    }

    public static SNForegroundCallbacks get(Application application) {
        if (INSTANCE == null) {
            init(application);
        }
        return INSTANCE;
    }

    public static SNForegroundCallbacks get(Context ctx) {
        if (INSTANCE == null) {
            Context appCtx = ctx.getApplicationContext();
            if (appCtx instanceof Application) {
                init((Application) appCtx);
            }
            throw new IllegalStateException(
                    "Foreground is not initialised and " +
                            "cannot obtain the Application object");
        }
        return INSTANCE;
    }

    public static SNForegroundCallbacks get() {
        if (INSTANCE == null) {
            throw new IllegalStateException(
                    "Foreground is not initialised - invoke " +
                            "at least once with parameterised init/get");
        }
        return INSTANCE;
    }

    public boolean isForeground() {
        return foreground;
    }

    public boolean isBackground() {
        return !foreground;
    }

    public void addListener(SNLifecycleListener listener) {
        listeners.add(listener);
    }

    public void removeListener(SNLifecycleListener listener) {
        listeners.remove(listener);
    }

    @Override
    public void onActivityResumed(Activity activity) {
        Class<? extends Activity> aClass = activity.getClass();
        if (whiteClass.contains(aClass)) {
            return;
        }

        paused = false;
        boolean wasBackground = !foreground;
        foreground = true;
        if (check != null) {
            handler.removeCallbacks(check);
        }
        if (wasBackground) {
            for (SNLifecycleListener l : listeners) {
                try {
                    l.onBecameForeground(activity);
                } catch (Exception exc) {
//                    L.d("Listener threw exception!:" + exc.toString());
                }
            }
        } else {
//            L.d("still foreground");
        }
    }

    @Override
    public void onActivityPaused(final Activity activity) {
        Class<? extends Activity> aClass = activity.getClass();
        if (whiteClass.contains(aClass)) {
            return;
        }
        paused = true;
        if (check != null) {
            handler.removeCallbacks(check);
        }
        check = new Runnable() {
            @Override
            public void run() {
                if (foreground && paused) {
                    foreground = false;
                    for (SNLifecycleListener l : listeners) {
                        try {
                            l.onBecameBackground(activity);
                        } catch (Exception exc) {
//                            L.d("Listener threw exception!:" + exc.toString());
                        }
                    }
                } else {
//                    L.d("still foreground");
                }
            }
        };

        handler.postDelayed(check, CHECK_DELAY);
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        if (listeners != null) {

            for (SNLifecycleListener l : listeners) {
                try {
                    l.onActivityCreated(activity);
                } catch (Exception exc) {
//                    L.d("Listener threw exception!:" + exc.toString());
                }
            }
        }
    }

    @Override
    public void onActivityStarted(Activity activity) {
        if (listeners != null) {

            for (SNLifecycleListener l : listeners) {
                try {
                    l.onActivityStarted(activity);
                } catch (Exception exc) {
//                    L.d("Listener threw exception!:" + exc.toString());
                }
            }
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        if (listeners != null) {

            for (SNLifecycleListener l : listeners) {
                try {
                    l.onActivityStopped(activity);
                } catch (Exception exc) {
//                    L.d("Listener threw exception!:" + exc.toString());
                }
            }
        }
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        if (listeners != null) {

            for (SNLifecycleListener l : listeners) {
                try {
                    l.onActivitySaveInstanceState(activity);
                } catch (Exception exc) {
//                    L.d("Listener threw exception!:" + exc.toString());
                }
            }
        }
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        if (listeners != null) {
            for (SNLifecycleListener l : listeners) {
                try {
                    l.onActivityDestroyed(activity);
                } catch (Exception exc) {
//                    L.d("Listener threw exception!:" + exc.toString());
                }
            }
        }
        if (null != handler && null != check) {
            handler.removeCallbacks(check);
            check = null;
        }
    }
}
